package com.headStorm;

import com.adobe.internal.xmp.XMPMeta;
import com.adobe.internal.xmp.XMPMetaFactory;
import com.adobe.internal.xmp.impl.XMPIteratorImpl;
import com.adobe.internal.xmp.properties.XMPPropertyInfo;

import java.io.*;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

/**
 * @author zhangqq
 * @create 2021-05-29 17:06
 **/
public class XMPUtil {

    private final byte[] OPEN_ARR = "<x:xmpmeta".getBytes();

    private final byte[] CLOSE_ARR = "</x:xmpmeta>".getBytes();

    private final String namespace = "http://www.xxxx.com.cn/xxxx/1.0/";

    private final String xmpTag = "xxxx:";

    private String orgPath ;

    private String destPath;

    private Map<String, String> xmpMap;

    /**
     * 添加图片XMP数据
     * @param orgPath 图片路径
     * @param destPath 生成图片路径
     * @param xmpMap 添加数据集
     */
    public void changeImgXMP(String orgPath, String destPath, Map<String, String> xmpMap){
        this.orgPath = orgPath;
        this.destPath = destPath;
        this.xmpMap = xmpMap;
        try{
            setXMP();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void setXMP()throws Exception{
        File orgFile = new File(orgPath);
        File destFile = new File(destPath);
        if(destFile.exists()){
            destFile.delete();
            destFile.createNewFile();
        }
        FileInputStream in = new FileInputStream(orgFile);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        copy(in, out);
        byte[] fileData = out.toByteArray();
        int openIdx = indexOf(fileData, OPEN_ARR, 0);
        if(openIdx>0){
            int closeIdx = indexOf(fileData, CLOSE_ARR, openIdx + 1) + CLOSE_ARR.length;
            byte[] beforeArr = Arrays.copyOfRange(fileData,0,openIdx);
            byte[] afterArr = Arrays.copyOfRange(fileData,closeIdx+1,fileData.length);
            byte[] xmpArr = Arrays.copyOfRange(fileData,openIdx,closeIdx);
            XMPMeta xmpMeta = XMPMetaFactory.parseFromBuffer(xmpArr);



            XMPMetaFactory.getSchemaRegistry().registerNamespace(namespace,xmpTag);
            addXMPMeta(xmpMeta);

            printXMPMeta(xmpMeta);

            ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();
            XMPMetaFactory.serialize(xmpMeta, xmpOut);
            byte[] xmpArrNew = xmpOut.toByteArray();
            FileOutputStream outputStream = new FileOutputStream(destFile);
            wirteByte(outputStream, beforeArr);
            wirteByte(outputStream, xmpArrNew);
            wirteByte(outputStream, afterArr);
            outputStream.close();
        }
    }

    private void wirteByte(OutputStream out, byte[] bytes) throws Exception{
        out.write(bytes);
        out.flush();
    }

    private void addXMPMeta(XMPMeta xmpMeta) throws Exception{
        Iterator<String> iter = xmpMap.keySet().iterator();
        while (iter.hasNext()){
            String key = iter.next();
            String value = xmpMap.get(key);
            xmpMeta.setProperty(namespace,xmpTag+key,value);
        }
    }

    private void printXMPMeta(XMPMeta xmpMeta) throws Exception{
        XMPIteratorImpl xmpIterator = (XMPIteratorImpl)xmpMeta.iterator();
        while (xmpIterator.hasNext()){
            XMPPropertyInfo obj = (XMPPropertyInfo)xmpIterator.next();
            System.out.println(obj.getNamespace()+"--"+obj.getPath()+"--"+obj.getValue());
        }
    }

    private void printXMPMeta(String filePath) throws Exception {
        FileInputStream in = new FileInputStream(new File(filePath));
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        copy(in, out);
        byte[] fileData = out.toByteArray();
        XMPMeta xmpMeta = XMPMetaFactory.parseFromBuffer(fileData);
        printXMPMeta(xmpMeta);
    }

    private int indexOf(byte[] arr, byte[] sub, int start){
        int subIdx = 0;
        for(int x = start;x < arr.length;x++) {
            if(arr[x] == sub[subIdx]){
                if(subIdx == sub.length - 1){
                    return x - subIdx;
                }
                subIdx++;
            } else{
                subIdx = 0;
            }
        }
        return -1;
    }

    private void copy(InputStream in, OutputStream out) throws Exception{
        int len = -1;
        byte[] buf = new byte[1024];
        while((len = in.read(buf)) >= 0)
        {
            out.write(buf, 0, len);
        }

        in.close();
        out.close();
    }

    public static void main(String[] args) throws Exception {
        new XMPUtil().printXMPMeta("D:\\ee\\DJI_0691.JPG");
    }
}
